package com.erp.erp_ui.warehouse.service;

import com.erp.enums.*;
import com.erp.erp_entitys.warehouse.entity.*;
import com.erp.erp_entitys.warehouse.req.DictionaryInfoReq;
import com.erp.erp_entitys.warehouse.req.InventoryListReq;
import com.erp.erp_entitys.warehouse.req.SelectStockReq;
import com.erp.erp_entitys.warehouse.rsp.DictionaryInfoRsp;
import com.erp.erp_servers.warehouse.*;
import com.erp.erp_ui.warehouse.enums.DataIsValidEnum;
import com.erp.erp_ui.warehouse.enums.DataSourceTitleEnum;
import com.erp.erp_ui.warehouse.req.*;
import com.erp.erp_ui.warehouse.vo.*;
import com.erp.utils.DateUtils;
import com.erp.utils.R;
import com.erp.utils.ResultStatusEnum;
import com.erp.utils.StringUtil;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : InventoryService
 * @Description : 盘点业务逻辑层
 * @Author : lst
 * @Date: 2020-07-24 14:42
 */
@Service
public class InventoryService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(InventoryService.class);

    /**
     * 盘点接口
     */
    private final IInventoryService inventoryService;

    /**
     * 盘点明细接口
     */
    private final IInventoryDetailService inventoryDetailService;

    /**
     * 库存接口
     */
    private final IStockService stockService;

    /**
     * 库存明细接口
     */
    private final IStockDetailService stockDetailService;

    /**
     * 附件接口
     */
    private final IAnnexService annexService;

    /**
     * 临时附件接口
     */
    private final ITempAnnexService tempAnnexService;

    @Autowired
    public InventoryService(IInventoryService inventoryService,
                            IInventoryDetailService inventoryDetailService,
                            IStockService stockService,
                            IStockDetailService stockDetailService,
                            IAnnexService annexService,
                            ITempAnnexService tempAnnexService) {
        this.inventoryService = inventoryService;
        this.inventoryDetailService = inventoryDetailService;
        this.stockService = stockService;
        this.stockDetailService = stockDetailService;
        this.annexService = annexService;
        this.tempAnnexService = tempAnnexService;
    }

    /**
     * 盘点首页-获取分页列表
     * @param req 查询参数
     * @return 分页信息
     */
    public PageInfo<InventoryListPageVo> getListByPage(InventoryListPageReq req){
        //初始化查询参数
        InventoryListReq listReq = new InventoryListReq();
        //赋值
        BeanUtils.copyProperties(req, listReq);
        //调用接口查询结果
        List<InventoryEntity> inventoryList = inventoryService.getInventoryInfo(listReq);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(inventoryList);
        //初始化回参对象
        List<InventoryListPageVo> pageVos = new ArrayList<>();
        if(CollectionUtils.isEmpty(inventoryList)){
            pageInfo.setList(pageVos);
            return pageInfo;
        }
        for(InventoryEntity inventory : inventoryList){
            InventoryListPageVo pageVo = new InventoryListPageVo();
            //赋值
            BeanUtils.copyProperties(inventory, pageVo);
            //处理操作时间
            pageVo.setOperationDate(DateUtils.format(inventory.getOperationDate(), DateUtils.DATE_PATTERN));
            //处理创建时间
            pageVo.setCreateDate(DateUtils.format(inventory.getCreateDate(), DateUtils.DATE_PATTERN));
            //处理数据状态
            pageVo.setStatusStr(OperationStatusEnum.getDescById(inventory.getStatus()));

            pageVos.add(pageVo);
        }
        pageInfo.setList(pageVos);
        return pageInfo;
    }

    /**
     * 获取库存信息
     * @param req 查询参数
     * @return 库存集合
     */
    public PageInfo<InventoryDetailStockProductVo> getStockList(InventoryDetailStockProductReq req){
        //初始化查询信息
        SelectStockReq stockReq = new SelectStockReq();
        //字段赋值
        BeanUtils.copyProperties(req, stockReq);
        //合同类型为待定
        stockReq.setContractType(ContractTypeEnum.TO_BE_DETERMINED.getId());
        //实际数量大于零
        stockReq.setZeroRealAvailable(0);
        //调用库存接口查询库存信息
        List<StockEntity> stocks = stockService.getStockListByQuery(stockReq);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(stocks);
        //初始化回参
        List<InventoryDetailStockProductVo> stockProductVos = new ArrayList<>();
        if(CollectionUtils.isEmpty(stocks)){
            pageInfo.setList(stockProductVos);
            return pageInfo;
        }
        for(StockEntity stock : stocks){
            InventoryDetailStockProductVo productVo = new InventoryDetailStockProductVo();
            //赋值
            BeanUtils.copyProperties(stock, productVo);
            //设置成本单价
            productVo.setCostUnitPrice(stock.getProductUnitPrice());
            //设置库存id
            productVo.setStockId(stock.getId());
            //设置仓库名称
            productVo.setWarehouseIdStr(stock.getWarehouseName());
            //设置实盘数量,默认为零
            productVo.setRealInventoryNum(new BigDecimal("0"));
            //设置抄库数量=现库存实际数量
            productVo.setCopyStockNum(stock.getRealQuantity());
            //设置盈亏数量,默认为零
            productVo.setProfitLossNum(new BigDecimal("0"));
            //设置盈亏金额,默认为零
            productVo.setProfitLossMoney(new BigDecimal("0"));
            //设置最低可盘点数量(调拨申请数量+出库申请数量)
            BigDecimal transferApplyQuantity = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getTransferApplyQuantity())){
                transferApplyQuantity = stock.getTransferApplyQuantity();
            }
            BigDecimal outStockApplyQuantity = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getOutWarehouseApply())){
                outStockApplyQuantity = stock.getOutWarehouseApply();
            }
            productVo.setCanInventoryLeastNum(transferApplyQuantity.add(outStockApplyQuantity));

            stockProductVos.add(productVo);
        }
        pageInfo.setList(stockProductVos);
        return pageInfo;
    }

    /**
     * 设置仓库信息
     * @param warehouseInfos 仓库信息集合
     * @param warehouseId 仓库编码
     */
    private String setWarehouse(List<DictionaryInfoRsp> warehouseInfos, String warehouseId){
        if(CollectionUtils.isEmpty(warehouseInfos) || StringUtils.isBlank(warehouseId)){
            return null;
        }
        for(DictionaryInfoRsp warehouseInfo : warehouseInfos){
            if(warehouseInfo.getCode().equals(warehouseId)){
                return warehouseInfo.getName();
            }
        }
        return null;
    }

    /**
     * 盘点新增
     * @param req 新增参数
     * @param creator 创建人
     * @param creatorNo 创建人编码
     * @throws ParseException
     */
    @Transactional(rollbackFor = Exception.class)
    public R add(AddInventoryReq req, String creator, String creatorNo) throws ParseException {
        boolean billNoCheckFlag = (null != req.getId() && req.getBillNo().equals(req.getNewBillNo()));
        if(!billNoCheckFlag){
            //单号做唯一校验
            boolean billNoFlag = checkRepeatBillNo(req.getBillNo());
            if(!billNoFlag){
                return R.buildError(ResultStatusEnum.BILL_NO_REPEAT);
            }
        }
        //新增、修改盘点主表信息并返回盘点id
        Integer id = addInventoryInfo(req, creator, creatorNo);
        if(null == id){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        //新增、修改盘点明细
        addInventoryDetailInfo(req, id, creator, creatorNo);
        //添加附件信息
        boolean flag = addAnnex(req.getAnnexList(), id, creator, creatorNo);
        if(!flag){
            LOGGER.info("仓库管理-其它出库-批量新增附件异常");
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        //删除临时附件信息
        deleteTempAnnex(req.getAnnexList());
        return R.build(ResultStatusEnum.SUCCESS);

    }

    /**
     * 批量处理临时附件信息，将临时附件设置为失效
     * @param annexReqs
     */
    private void deleteTempAnnex(List<AnnexReq> annexReqs){
        //没有附件
        if(CollectionUtils.isEmpty(annexReqs)){
            return;
        }
        //存在附件
        for(AnnexReq annex : annexReqs){
            if(null != annex.getNews()){
                //旧附件,不用修改
                continue;
            }
            TempAnnexEntity tempAnnex = new TempAnnexEntity();
            //设置临时附件id
            tempAnnex.setId(annex.getId());
            //设置修改时间
            tempAnnex.setUpdateTime(new Date());
            //将附件设置为失效
            tempAnnex.setValid(0);
            tempAnnexService.update(tempAnnex);
        }

    }

    /**
     * 附件新增
     * @param annexReqs 附件信息
     * @param id 盘点id
     * @param operator 操作人
     * @param operatorNo 操作人编码
     * @return 是否新增成功(true:成功 false:失败 )
     */
    private boolean addAnnex(List<AnnexReq> annexReqs, Integer id, String operator, String operatorNo) {
        try {
            //没有附件,不新增
            if(CollectionUtils.isEmpty(annexReqs)){
                return true;
            }
            //存在附件,新增附件信息
            List<AnnexEntity> list = new ArrayList<>();
            //获取旧的附件id集合
            List<Integer> oldIds = new ArrayList<>();
            for(AnnexReq annexReq : annexReqs){
                if(null != annexReq.getNews()){
                    //属于旧附件 只取id,不新增
                    oldIds.add(annexReq.getId());
                    continue;
                }
                AnnexEntity annex = new AnnexEntity();
                BeanUtils.copyProperties(annexReq, annex);
                //设置关联模块id
                annex.setModuleId(ModuleTypeEnum.WAREHOUSE_INVENTORY.getId());
                //设置关联模块父id
                annex.setParentId(id);
                //设置上传时间
                annex.setUploadTime(DateUtils.convertStringToDate(annexReq.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置修改时间
                annex.setUpdateTime(new Date());
                //设置操作人
                annex.setOperator(operator);
                //设置操作人编码
                annex.setOperatorNo(operatorNo);
                //设置数据有效
                annex.setValid(1);

                list.add(annex);
            }
            if(oldIds.size() > 0){
                //通过调拨id获取修改附件信息
                AnnexEntity annex = new AnnexEntity();
                annex.setModuleId(ModuleTypeEnum.WAREHOUSE_INVENTORY.getId());
                annex.setParentId(id);
                //获取上次附件信息
                List<AnnexEntity> annexList = annexService.queryAll(annex);
                if(!CollectionUtils.isEmpty(annexList)){
                    //获取上次附件id集合
                    List<Integer> oldAnnexIds = annexList.stream().map(p -> p.getId()).collect(Collectors.toList());
                    //得到被删除的附件id
                    Collection collection = new ArrayList(oldAnnexIds);
                    collection.removeAll(oldIds);
                    if(collection.size() > 0){
                        Iterator<Integer> it = collection.iterator();
                        while (it.hasNext()){
                            int nowId = it.next();
                            AnnexEntity annexEntity = new AnnexEntity();
                            annexEntity.setId(nowId);
                            //将被删除的附件设为失效
                            annexEntity.setValid(DataIsValidEnum.INVALID.getId());

                            annexService.update(annexEntity);
                        }
                    }
                }
            }
            if(!CollectionUtils.isEmpty(list)){
                //附件批量新增
                int res = annexService.batchInsert(list);
                if(res == list.size()){
                    return true;
                }
            }
            return true;
        }catch (Exception e){
            throw new RuntimeException();
        }
    }

    /**
     * 新增、修改盘点明细
     * @param req 盘点信息
     * @param id 盘点id
     * @param creator 创建人
     * @param creatorNo 创建人编码
     */
    private void addInventoryDetailInfo(AddInventoryReq req, Integer id, String creator, String creatorNo){
        if(!CollectionUtils.isEmpty(req.getDetails())){
            //获取修改明细id集合
            List<Integer> newIds = new ArrayList<>();
            //新增明细集合
            List<InventoryDetailEntity> addDetails = new ArrayList<>();
            for(InventoryDetailReq detailReq : req.getDetails()){
                //初始化调拨明细对象
                InventoryDetailEntity detail = new InventoryDetailEntity();
                //赋值
                BeanUtils.copyProperties(detailReq, detail);
                //设置id
                detail.setInventoryId(id);
                //分摊费用单价
                BigDecimal shareCostPrice = detailReq.getShareCostPrice();
                //成本单价
                BigDecimal costUnitPrice = detailReq.getCostUnitPrice();
                //获取实盘数量
                BigDecimal realInventoryNum = detailReq.getRealInventoryNum();
                //获取抄库数量
                BigDecimal copyStockNum = detailReq.getCopyStockNum();
                //设置盈亏数量=实盘数量-抄库数量
                BigDecimal profitLossNum = realInventoryNum.subtract(copyStockNum);
                detail.setProfitLossNum(profitLossNum);
                //设置盈亏金额 = (成本单价+分摊费用单价)*盈亏数量
                BigDecimal profitLossMoney = (costUnitPrice.add(shareCostPrice)).multiply(profitLossNum);
                detail.setProfitLossMoney(profitLossMoney);

                //库存明细新增
                int stockDetailId = addStockDetail(detailReq, req.getBillNo(), creator, creatorNo);

                if(null == detailReq.getId()){
                    //新增

                    //设置数据有效性(0:无效 1:有效)
                    detail.setValid(DataIsValidEnum.VALID.getId());
                    //设置明细库存id
                    detail.setStockDetailId(stockDetailId);
                    addDetails.add(detail);
                }else {
                    //修改

                    //获取明细id
                    newIds.add(detailReq.getId());
                    inventoryDetailService.update(detail);
                }

            }

            //处理被删除的盘点明细明细
            handleBeenDeletedDetail(req, id, newIds);

            if(!CollectionUtils.isEmpty(addDetails)){
                //调用接口保存盘点明细
                inventoryDetailService.insertInventoryDetailList(addDetails);
            }
        }
    }

    /**
     * 处理被删除的盘点明细
     * @param req 盘点明细
     * @param id 盘点id
     * @param newIds 修改后未被删除的盘点明细id集合
     */
    private void handleBeenDeletedDetail(AddInventoryReq req, int id, List<Integer> newIds){
        if(null != req.getId()){
            //修改-找出被删除的出库明细

            InventoryDetailEntity inventoryDetailReq = new InventoryDetailEntity();
            //设置id
            inventoryDetailReq.setInventoryId(id);
            //查询有效数据
            inventoryDetailReq.setValid(DataIsValidEnum.VALID.getId());
            //调用接口查询结果
            List<InventoryDetailEntity> inventoryDetails = inventoryDetailService.queryAll(inventoryDetailReq);
            if(!CollectionUtils.isEmpty(inventoryDetails)){
                //获取盘点明细id和库存明细id
                Map<String, Map<Integer, Integer>> stockIdAndStockDetailIdMap = getStockIdAndStockDetailIdMap(inventoryDetails);
                //获取盈亏数量
                Map<Integer, BigDecimal> profitLossNumMap = getProfitLossNumMap(inventoryDetails);
                //获取id集合
                List<Integer> oldIds = inventoryDetails.stream().map(p -> p.getId()).collect(Collectors.toList());
                //找出被删除的id
                Collection collection = new ArrayList(oldIds);
                collection.removeAll(newIds);
                if(collection.size() > 0){
                    //遍历删除被删除的明细
                    Iterator<Integer> ids = collection.iterator();
                    while (ids.hasNext()){
                        int deletedId = ids.next();
                        if(null != req.getStatus() && req.getStatus().equals(OperationStatusEnum.APPROVED_BOX.getId())){
                            //如果审批完成后的数据被删除,则还需要回退 实际数量、实际可用数量、可申请数量
                            Integer stockId = stockIdAndStockDetailIdMap.get("stockIdMap").get(deletedId);
                            //获取库存数据
                            StockEntity stock = stockService.getStockById(stockId);
                            //初始化库存对象
                            StockEntity stockReq = new StockEntity();
                            //设置修改主键
                            stockReq.setId(stockId);
                            //获取盈亏数量
                            BigDecimal profitLossNum = profitLossNumMap.get(deletedId);
                            //设置新的实际数量=实际数量+盈亏数量
                            stockReq.setRealQuantity(stock.getRealQuantity().add(profitLossNum));
                            //设置新的实际可用数量=实际可用数量+盈亏数量
                            stockReq.setRealAvailableQuantity(stock.getRealAvailableQuantity().add(profitLossNum));
                            //设置新的可申请数量=可申请数量+盈亏数量
                            stockReq.setCanApplyQuantity(stock.getCanApplyQuantity().add(profitLossNum));
                            //回退删除的出库数量
                            stockService.update(stockReq);
                        }

                        InventoryDetailEntity detail = new InventoryDetailEntity();
                        //设置修改主键id
                        detail.setId(deletedId);
                        //设置为失效
                        detail.setValid(DataIsValidEnum.INVALID.getId());
                        //将删除的盘点明细设为无效
                        inventoryDetailService.update(detail);
                        //通过盘点明细id获取库存库存明细id
                        Integer stockDetailId = stockIdAndStockDetailIdMap.get("stockDetailIdMap").get(deletedId);
                        //将库存明细设为无效
                        StockDetailEntity stockDetail = new StockDetailEntity();
                        stockDetail.setId(stockDetailId);
                        stockDetail.setValid(DataIsValidEnum.INVALID.getId());
                        stockDetailService.update(stockDetail);
                    }
                }
            }
        }
    }

    /**
     * 获取盈亏数量
     * @param inventoryDetails 盘点明细对象
     * @return key为盘点明细id value为盈亏数量
     */
    private Map<Integer, BigDecimal> getProfitLossNumMap(List<InventoryDetailEntity> inventoryDetails){
        Map<Integer, BigDecimal> profitLossNumMap = new HashMap<>(inventoryDetails.size());
        for(InventoryDetailEntity inventoryDetail : inventoryDetails){
            profitLossNumMap.put(inventoryDetail.getId(), inventoryDetail.getProfitLossNum());
        }
        return profitLossNumMap;
    }

    /**
     * 获取库存id和库存明细id
     * @param inventoryDetails 盘点明细对象
     * @return key为盘点明细id value为库存id和库存明细id
     */
    private Map<String, Map<Integer, Integer>> getStockIdAndStockDetailIdMap(List<InventoryDetailEntity> inventoryDetails){
        //获取集合大小
        int size = inventoryDetails.size();
        //库存明细id
        Map<Integer, Integer> stockDetailIdMap = new HashMap<>(size);
        //库存id
        Map<Integer, Integer> stockIdMap = new HashMap<>(size);
        for(InventoryDetailEntity inventoryDetail : inventoryDetails){
            stockDetailIdMap.put(inventoryDetail.getId(), inventoryDetail.getStockDetailId());
            stockIdMap.put(inventoryDetail.getId(), inventoryDetail.getStockId());
        }
        Map<String, Map<Integer, Integer>> map = new HashMap<>(3);
        map.put("stockDetailIdMap", stockDetailIdMap);
        map.put("stockIdMap", stockIdMap);
        return map;
    }

    /**
     * 新增库存明细
     * @param detailReq 出库明细
     * @param billNo 单号
     * @param creator 创建人
     * @param createNo 创建人编码
     */
    private int addStockDetail(InventoryDetailReq detailReq, String billNo, String creator, String createNo){
        //初始化库存明细对象
        StockDetailEntity stockDetail = new StockDetailEntity();
        //赋值
        BeanUtils.copyProperties(detailReq, stockDetail);
        //设置标题
        stockDetail.setTitle(DataSourceTitleEnum.INVENTORY.getDesc());
        //设置单据编号
        stockDetail.setInvoiceNumber(billNo);
        //设置单价
        stockDetail.setUnitPrice(detailReq.getCostUnitPrice());
        //设置数量
        stockDetail.setQuantity(detailReq.getRealInventoryNum());
        //设置模块id
        stockDetail.setModuleId(ModuleTypeEnum.WAREHOUSE_INVENTORY.getId());
        //设置创建人
        stockDetail.setInStorePerson(creator);
        //设置创建人编码
        stockDetail.setInStoreCode(createNo);
        //设置操作人
        stockDetail.setOperator(creator);
        //设置操作人编码
        stockDetail.setOperationCode(createNo);
        if(null == detailReq.getId()){
            //新增

            //设置创建时间
            stockDetail.setCreateDate(new Date());
            //设置有效性
            stockDetail.setValid(DataIsValidEnum.VALID.getId());
            stockDetailService.insert(stockDetail);

        }else {
            //修改

            stockDetail.setId(detailReq.getStockDetailId());
            stockDetailService.update(stockDetail);
        }

        return stockDetail.getId();
    }

    /**
     * 新增盘点信息
     * @param req 盘点信息
     * @param creator 创建人
     * @param creatorNo 创建人编码
     * @return 盘点id
     * @throws ParseException
     */
    private Integer addInventoryInfo(AddInventoryReq req, String creator, String creatorNo) throws ParseException {
        //初始化盘点对象
        InventoryEntity inventory = new InventoryEntity();
        //字段赋值
        BeanUtils.copyProperties(req, inventory);
        //设置盘点时间
        inventory.setOperationDate(DateUtils.convertStringToDate(req.getOperationDate(), DateUtils.DATE_PATTERN));
        //设置创建人
        inventory.setCreator(creator);
        //设置创建人编码
        inventory.setCreatorNo(creatorNo);
        //设置状态 默认草稿箱
        inventory.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
        if(null == req.getId()){
            //新增

            //设置创建时间
            inventory.setCreateDate(new Date());

            inventoryService.insert(inventory);
        }else {
            //修改
            inventoryService.update(inventory);

        }

        return inventory.getId();
    }

    /**
     * 校验单号是否存在
     * @param billNo 单号
     * @return true:不重复 false:重复
     */
    private boolean checkRepeatBillNo(String billNo){
        InventoryEntity req = new InventoryEntity();
        req.setBillNo(billNo);
        List<InventoryEntity> list = inventoryService.queryAll(req);
        if(CollectionUtils.isEmpty(list)){
            return true;
        }
        return false;
    }

    /**
     * 盘点更新库存信息
     * @param inventoryId 盘点id
     * @param creator 创建者
     * @param creatorNo 创建者编码
     */
    private void updateStock(Integer inventoryId, String creator, String creatorNo){
        if(null == inventoryId) {
            LOGGER.error("仓库管理-盘点-修改库存信息异常,inventoryId为空");
            return;
        }
        //获取盘点信息
        InventoryEntity inventory = inventoryService.getInventoryById(inventoryId);
        if(null == inventory){
            LOGGER.error("仓库管理-盘点-通过盘点id获取盘点信息为空");
            return;
        }
        //初始化查询对象
        InventoryDetailEntity inventoryDetailReq = new InventoryDetailEntity();
        //设置查询条件
        inventoryDetailReq.setInventoryId(inventoryId);
        //通过inventoryId获取盘点详情对象
        List<InventoryDetailEntity> inventoryDetails = inventoryDetailService.queryAll(inventoryDetailReq);
        if(inventoryDetails.isEmpty()){
            LOGGER.error("仓库管理-盘点-通过盘点id获取盘点详情信息为空");
            return;
        }
        for(InventoryDetailEntity inventoryDetail : inventoryDetails){
            //初始化库存对象
            StockEntity stock = new StockEntity();
            int id = inventoryDetail.getStockId();
            //设置库存id
            stock.setId(id);
            //实际数量 = 实盘数量
            BigDecimal realInventoryNum = inventoryDetail.getRealInventoryNum();
            stock.setRealQuantity(realInventoryNum);
            //实际可用 = 实盘数量
            stock.setRealAvailableQuantity(realInventoryNum);
            //托盘入数
            BigDecimal trayNumber = inventoryDetail.getTrayNumber();
            if(StringUtil.isNotEmpty(realInventoryNum) && StringUtil.isNotEmpty(trayNumber)){
                //重新计算总托盘(实盘数量/托盘入数)
                stock.setTotalTray(realInventoryNum.divide(trayNumber, 2, BigDecimal.ROUND_HALF_UP));
            }

            //更新库存信息
            stockService.update(stock);

            //初始化库存明细
            StockDetailEntity stockDetail = new StockDetailEntity();
            //库存id
            stockDetail.setStockId(id);
            //标题(来源盘点)
            stockDetail.setTitle(DataSourceTitleEnum.INVENTORY.getDesc());
            //模块id(来源盘点)
            stockDetail.setModuleId(DataSourceTitleEnum.INVENTORY.getId());
            //单据编号(盘点单号)
            stockDetail.setInvoiceNumber(inventory.getBillNo());
            //仓库id
            //stockDetail.setWarehouseId(inventoryDetail.getWarehouseId());
            System.out.println("待处理");
            //产品编码
            stockDetail.setProductCode(inventoryDetail.getProductCode());
            //规格编码
            stockDetail.setSpecificationCode(inventoryDetail.getSpecificationCode());
            //颜色
            stockDetail.setColor(inventoryDetail.getColor());
            //成本单价
            stockDetail.setUnitPrice(inventoryDetail.getCostUnitPrice());
            //数量
            stockDetail.setQuantity(inventoryDetail.getRealInventoryNum());
            //标准单位数量
            stockDetail.setStandardUnitQuantity(inventoryDetail.getRealInventoryNum());
            //标准单位
            stockDetail.setStandardUnit(inventoryDetail.getProductUnit());
            //创建时间
            stockDetail.setCreateDate(new Date());
            //入库人
            stockDetail.setInStorePerson(creator);
            //入库人编码
            stockDetail.setInStoreCode(creatorNo);
            //操作人
            stockDetail.setOperator(inventory.getCreator());
            //操作人编码
            stockDetail.setOperationCode(inventory.getCreatorNo());
            //规格说明
            stockDetail.setProductSpecExplanation(inventoryDetail.getSpecificationExplanation());
            //备注
            stockDetail.setMemo(inventory.getMemo());

            //新增库存明细
            stockDetailService.insert(stockDetail);
        }


    }

    /**
     * 获取盘点详情信息
     * @param id 盘点id
     * @param flag true:修改 false:详情
     * @return 盘点详情信息
     */
    public InventoryDetailAndUpdateVo getInventoryDetailInfo(Integer id, boolean flag){
        //初始化回参对象集合
        InventoryDetailAndUpdateVo vo = new InventoryDetailAndUpdateVo();
        if(null == id){
            return vo;
        }

        //第一步：获取主表信息
        InventoryEntity inventory = inventoryService.getInventoryById(id);
        if(null == inventory || null == inventory.getId()){
            return vo;
        }
        //赋值
        BeanUtils.copyProperties(inventory, vo);
        //设置盘点时间
        vo.setOperationDate(DateUtils.format(inventory.getOperationDate(), DateUtils.DATE_PATTERN));
        //设置创建时间
        vo.setCreateDate(DateUtils.format(inventory.getCreateDate(), DateUtils.DATE_PATTERN));

        //第二步：获取对应产品信息
        InventoryDetailEntity inventoryDetail = new InventoryDetailEntity();
        //设置盘点id
        inventoryDetail.setInventoryId(id);
        //设置数据为有效
        inventoryDetail.setValid(DataIsValidEnum.VALID.getId());

        List<InventoryDetailEntity> inventoryDetails = inventoryDetailService.queryAll(inventoryDetail);
        //获取所有仓库字典信息
        DictionaryInfoReq dictionaryInfosReq = new DictionaryInfoReq();
        //仓库维护
        dictionaryInfosReq.setType(DictionaryTypeEnum.WAREHOUSE_MAINTENANCE.getId());
        //主仓库维护
        dictionaryInfosReq.setLx(DictionaryLxEnum.MAIN_WAREHOUSE_MAINTENANCE.getId());
        List<DictionaryInfoRsp> warehouseInfos = stockService.getDictionaryInfo(dictionaryInfosReq);
        if(!CollectionUtils.isEmpty(inventoryDetails)){
            List<InventoryDetailVo> productVos = inventoryDetails.stream().map(p -> {
                InventoryDetailVo productVo = new InventoryDetailVo();
                //赋值
                BeanUtils.copyProperties(p, productVo);
                //设置仓库名称
                productVo.setWarehouseIdStr(setWarehouse(warehouseInfos, p.getWarehouseId()));
                //创建时间转化
                productVo.setCreateDate(DateUtils.format(p.getCreateDate(), DateUtils.DATE_PATTERN));

                if(flag){
                    //根据库存id获取最新 最低可盘点数
                    StockEntity stock = stockService.getStockById(p.getStockId());
                    //设置最低可盘点数量(调拨申请数量+出库申请数量)
                    BigDecimal transferApplyQuantity = new BigDecimal("0");
                    if(StringUtil.isNotEmpty(stock.getTransferApplyQuantity())){
                        transferApplyQuantity = stock.getTransferApplyQuantity();
                    }
                    BigDecimal outStockApplyQuantity = new BigDecimal("0");
                    if(StringUtil.isNotEmpty(stock.getOutWarehouseApply())){
                        outStockApplyQuantity = stock.getOutWarehouseApply();
                    }
                    productVo.setCanInventoryLeastNum(transferApplyQuantity.add(outStockApplyQuantity));
                    //获取分摊费用单价
                    productVo.setShareCostPrice(stock.getShareCostPrice());
                    //默认设置该单据不可删除
                    productVo.setDeleteFlag(false);
                    //获取抄库数量
                    BigDecimal copyStockNum = p.getCopyStockNum();
                    //获取库存可申请数量
                    BigDecimal canApplyQuantity = stock.getCanApplyQuantity();
                    //获取盈亏数量
                    BigDecimal profitLossNum = p.getProfitLossNum();
                    if(profitLossNum.compareTo(BigDecimal.ZERO) == 1){
                        //盘盈
                        if(StringUtil.isNotEmpty(canApplyQuantity) && StringUtil.isNotEmpty(copyStockNum)){
                            if(canApplyQuantity.compareTo(copyStockNum) > -1){
                                //可申请数量大于等于抄库数量 可删除
                                productVo.setDeleteFlag(true);
                            }
                        }
                    }else{
                        //盘亏 可直接删除
                        productVo.setDeleteFlag(true);
                    }
                }
                return productVo;
            }).collect(Collectors.toList());

            vo.setDetailVos(productVos);
        }

        //第三步：获取附件信息
        AnnexEntity annex = new AnnexEntity();
        annex.setModuleId(ModuleTypeEnum.WAREHOUSE_INVENTORY.getId());
        annex.setParentId(id);
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if(!CollectionUtils.isEmpty(annexList)){
            List<AnnexVo> annexVos = annexList.stream().map(p -> {
                AnnexVo annexVo = new AnnexVo();
                //赋值
                BeanUtils.copyProperties(p, annexVo);
                //上传时间转换
                annexVo.setUploadTime(DateUtils.format(p.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置附件为旧附件,用以区分修改时附件状态
                annexVo.setNews(0);

                return annexVo;
            }).collect(Collectors.toList());

            vo.setAnnexVos(annexVos);
        }
        return vo;
    }

    /**
     * 删除盘点信息(修改数据有效性)
     * @param id 盘点id
     * @param status 状态(1.草稿箱 2.待批箱 3.已批箱 4.完成箱 5.垃圾箱)
     */
    @Transactional(rollbackFor = Exception.class)
    public R delete(Integer id, Integer status){
        if(null == id){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        InventoryEntity inventoryReq = new InventoryEntity();
        inventoryReq.setId(id);
        if(OperationStatusEnum.DRAFT_BOX.getId() == status){
            //草稿箱删除：数据设为垃圾箱
            inventoryReq.setStatus(OperationStatusEnum.TRASH_CAN.getId());
        }else if(OperationStatusEnum.TRASH_CAN.getId() == status){
            //垃圾箱删除：数据回退到草稿箱
            inventoryReq.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
        }
        inventoryService.update(inventoryReq);
        //获取盘点明细数据
        InventoryDetailEntity inventoryDetail = new InventoryDetailEntity();
        inventoryDetail.setInventoryId(id);
        inventoryDetail.setValid(DataIsValidEnum.VALID.getId());
        //获取盘点明细
        List<InventoryDetailEntity> inventoryDetails = inventoryDetailService.queryAll(inventoryDetail);
        if(CollectionUtils.isEmpty(inventoryDetails)){
            //没有盘点明细,只删除盘点主表数据
            return R.build("");
        }
        for(InventoryDetailEntity detail : inventoryDetails){
            //盘点数量不为空
            if(StringUtil.isNotEmpty(detail.getRealInventoryNum())){
                //库存明细修改
                StockDetailEntity stockDetail = new StockDetailEntity();
                stockDetail.setId(detail.getStockDetailId());

                //将盘点明细修改
                InventoryDetailEntity inventoryDetailReq = new InventoryDetailEntity();
                inventoryDetailReq.setId(detail.getId());

                if(OperationStatusEnum.DRAFT_BOX.getId() == status){
                    //将库存明细设为失效
                    stockDetail.setValid(DataIsValidEnum.INVALID.getId());
                    //将盘点明细设为失效
                    inventoryDetailReq.setValid(DataIsValidEnum.INVALID.getId());
                }else if(OperationStatusEnum.TRASH_CAN.getId() == status){
                    //将库存明细设为有效
                    stockDetail.setValid(DataIsValidEnum.VALID.getId());
                    //将盘点明细设为有效
                    inventoryDetailReq.setValid(DataIsValidEnum.VALID.getId());
                }
                //修改库存明细状态
                stockDetailService.update(stockDetail);
                //修改调拨明细状态
                inventoryDetailService.update(inventoryDetailReq);
            }
        }
        return R.build("");
    }

    /**
     * 盘点数据操作接口
     * @param id 盘点id
     * @param operation 操作类型
     * 1.提交审批 2.审批通过 3.审批退回 4.完成 5.还原
     * 箱体：1.草稿箱 2.待批箱 3.已批箱 4.完成箱 5.垃圾箱
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public R operation(Integer id, Integer operation){
        if(null == id || null == operation){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        InventoryEntity inventory = new InventoryEntity();
        //设置id
        inventory.setId(id);
        if(operation == SubmitStatusEnum.SUBMIT_APPROVE.getId()){
            //提交审批后,状态为待批箱
            //状态设为待批箱
            inventory.setStatus(OperationStatusEnum.PENDING_BOX.getId());
        }else if(operation == SubmitStatusEnum.APPROVE_SUCCESS.getId()){
            //审批通过后,状态为已审批,库存实际数量和实际可用数量和可申请数量需要加上盈亏数量
            inventoryApproved(id);
            inventory.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
        }else if(operation == SubmitStatusEnum.APPROVE_RETURN.getId()){
            //审批退回后只修改调拨状态
            //状态设为草稿箱
            inventory.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
        }else if(operation == SubmitStatusEnum.SUCCESS.getId()){
            //将状态设为完成
            inventory.setStatus(OperationStatusEnum.COMPLETION_BOX.getId());
        }else if(operation == SubmitStatusEnum.REDUCTION.getId()){
            //将状态改为草稿箱
            inventory.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
        }
        //修改数据
        inventoryService.update(inventory);
        return R.build("");
    }

    /**
     * 盘点审批
     * @param id
     */
    private void inventoryApproved(Integer id){
        //初始化查询参数对象
        InventoryDetailEntity detailReq = new InventoryDetailEntity();
        detailReq.setInventoryId(id);
        detailReq.setValid(DataIsValidEnum.VALID.getId());
        List<InventoryDetailEntity> detailList = inventoryDetailService.queryAll(detailReq);
        if(CollectionUtils.isEmpty(detailList)){
            return;
        }
        for(InventoryDetailEntity detail : detailList){
            //获取库存id
            Integer stockId = detail.getStockId();
            //根据库存id获取库存信息
            StockEntity stock = stockService.getStockById(stockId);
            if(null == stock){
                return;
            }
            //修改最新库存实际数量和实际可用数量
            StockEntity stockReq = new StockEntity();
            //设置修改id
            stockReq.setId(stockId);
            //获取盈亏数量
            BigDecimal profitLossNum = detail.getProfitLossNum();
            //设置新的实际数量=实际数量+盈亏数量
            stockReq.setRealQuantity(stock.getRealQuantity().add(profitLossNum));
            //设置新的实际可用数量=实际可用数量+盈亏数量
            stockReq.setRealAvailableQuantity(stock.getRealAvailableQuantity().add(profitLossNum));
            //设置新的可申请数量=可申请数量+盈亏数量
            stockReq.setCanApplyQuantity(stock.getCanApplyQuantity().add(profitLossNum));

            //调用接口进行修改
            stockService.update(stockReq);
        }
    }

}
